package com.ccapton.dragview;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class DragView extends RelativeLayout implements View.OnTouchListener {

    private String TAG = "DragView";

    // view移动方向
    private static final int TOP = 21;
    private static final int LEFT = 22;
    private static final int BOTTOM = 23;
    private static final int RIGHT = 24;
    private static final int CENTER = 25;
    private int dragDirection;
    private int offset = 40;
    private int defaultAlignDistance = 40;

    private float alignDistance;

    private boolean leftAlign = true;
    private boolean rightAlign = true;
    private boolean topAlign = true;
    private boolean bottomAlign = true;

    private OnDragViewClickListener onDragViewClickListener;
    private LinearLayout llContent;


    public interface OnDragViewClickListener {
        void onDragViewClick(View view);
    }

    public float getAlignDistance() {
        return alignDistance;
    }

    public void setAlignDistance(float alignDistance) {
        this.alignDistance = alignDistance;
    }

    public boolean isLeftAlign() {
        return leftAlign;
    }

    public void setLeftAlign(boolean leftAlign) {
        this.leftAlign = leftAlign;
    }

    public boolean isRightAlign() {
        return rightAlign;
    }

    public void setRightAlign(boolean rightAlign) {
        this.rightAlign = rightAlign;
    }

    public boolean isTopAlign() {
        return topAlign;
    }

    public void setTopAlign(boolean topAlign) {
        this.topAlign = topAlign;
    }

    public boolean isBottomAlign() {
        return bottomAlign;
    }

    public void setBottomAlign(boolean bottomAlign) {
        this.bottomAlign = bottomAlign;
    }

    public OnDragViewClickListener getOnDragViewClickListener() {
        return onDragViewClickListener;
    }

    public void setOnDragViewClickListener(OnDragViewClickListener onDragViewClickListener) {
        this.onDragViewClickListener = onDragViewClickListener;
    }

    public DragView(Context context) {
        this(context, null);
    }

    public DragView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setupStyleable(context, attrs);
        setOnTouchListener(this);
        setFocusableInTouchMode(true);
        setClickable(true);
        setFocusable(true);

    }

    private void initView() {
        if(llContent==null){
            llContent = findViewById(R.id.dragView_content);
//            Log.e(TAG, "initView: "+ llContent);
        }
    }


    public void setupStyleable(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DragView);

        leftAlign = typedArray.getBoolean(R.styleable.DragView_leftAlign, true);
        rightAlign = typedArray.getBoolean(R.styleable.DragView_rightAlign, true);
        topAlign = typedArray.getBoolean(R.styleable.DragView_topAlign, true);
        bottomAlign = typedArray.getBoolean(R.styleable.DragView_bottomAlign, true);

        alignDistance = typedArray.getDimension(R.styleable.DragView_alignDistance, defaultAlignDistance);

        typedArray.recycle();

    }

    protected float dp2px(float dp) {
        DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
        return Math.round(dp * (displayMetrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
    }

    private float oldX, oldY;

    private int pressCount = 0;


    //调用该方法需要传入放置View的矩形空间左上角left、top值和右下角right、bottom值。这四个值是相对于父控件而言的。
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        Log.e(TAG, "onLayout=============: " + getWidth() + "  " + l + "  " + t + "  " + r + "  " + b);

        initView();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //测量所有子控件的宽和高
//        measureChildren(widthMeasureSpec,heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
//        Log.e(TAG, "onTouchEvent: "+event.getAction());
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                pressCount++;
                oldX = event.getX();
                oldY = event.getY();
                return super.onTouchEvent(event);
            case MotionEvent.ACTION_MOVE:
                pressCount++;
                float distanceX = event.getX() - oldX;
                float distanceY = event.getY() - oldY;
                if (Math.abs(distanceX) >= 5 || Math.abs(distanceY) >= 5) {
                    int l = (int) (getLeft() + distanceX);
                    int t = (int) (getTop() + distanceY);
                    int r = l + getWidth();
                    int b = t + getHeight();

                    if (l <= 0) {
                        l = 0;
                        r = getWidth();
                    } else if (r > ((ViewGroup) getParent()).getWidth()) {
                        r = ((ViewGroup) getParent()).getWidth();
                        l = ((ViewGroup) getParent()).getWidth() - getWidth();
                    }
                    if (t <= 0) {
                        t = 0;
                        b = getHeight();
                    } else if (b > ((ViewGroup) getParent()).getHeight()) {
                        b = ((ViewGroup) getParent()).getHeight();
                        t = ((ViewGroup) getParent()).getHeight() - getHeight();
                    }
                    this.layout(l, t, r, b);
//                    this.setTranslationX(l);
                }
                break;

            case MotionEvent.ACTION_UP:
                if (pressCount == 1) {
                    if (this.onDragViewClickListener != null) {
                        this.onDragViewClickListener.onDragViewClick(this);
                    }
                }
                pressCount = 0;

                if (getX() <= alignDistance) {
                    if (leftAlign) {
                        this.layout(0, (int) getY(), getWidth(), (int) getY() + getHeight());
//                        this.setTranslationX(0);
                    }
                } else if (getX() + getWidth() >= ((ViewGroup) getParent()).getWidth() - alignDistance) {
                    if (rightAlign) {
                        this.layout(((ViewGroup) getParent()).getWidth() - getWidth(), (int) getY(), ((ViewGroup) getParent()).getWidth(), (int) getY() + getHeight());
//                        this.setTranslationX(((ViewGroup) getParent()).getWidth() - getWidth());
                    }
                }
                if (getY() <= alignDistance) {
                    if (topAlign) {
                        this.layout((int) getX(), 0, (int) getX() + getWidth(), getHeight());
//                        this.setTranslationX((int) getX());
                    }
                } else if (getY() + getHeight() >= ((ViewGroup) getParent()).getHeight() - alignDistance) {
                    if (bottomAlign) {
                        this.layout((int) getX(), ((ViewGroup) getParent()).getHeight() - getHeight(), (int) getX() + getWidth(), ((ViewGroup) getParent()).getHeight());
//                        this.setTranslationX((int) getX());
                    }
                }
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.getParent().requestDisallowInterceptTouchEvent(true);
        int action = event.getAction();
        if (action == MotionEvent.ACTION_DOWN) {
            lastX = (int) event.getRawX();
            lastY = (int) event.getRawY();
            downx = (int) event.getRawX();
            downy = (int) event.getRawY();
            dragDirection = getDirection(v, (int) event.getX(), (int) event.getY());
//            Log.e(TAG, "onTouch: " + dragDirection);
        }
        if(dragDirection==LEFT||dragDirection==RIGHT){
            if (action == MotionEvent.ACTION_DOWN) {
//                Log.e(TAG, "onTouch:getWidth "+getWidth() );
                width = getWidth();
            }
            handleDrag(v, event, action);
            invalidate();
            return true;
        }
        return false;
    }

    private int endh;
    private int endw;
    private int lastX;
    private int lastY;
    private int downx;
    private int downy;

    private void handleDrag(View v, MotionEvent event, int action) {
        switch (action) {
            case MotionEvent.ACTION_UP:
                endw = getWidth();
                endh = getHeight();
                dragDirection = 0;
                break;
            case MotionEvent.ACTION_MOVE:
//                Log.e(TAG, "handleDrag: "+event.getRawX()+"  "+lastX );
                int dx = ((int) event.getRawX()) - lastX;
                switch (dragDirection) {
                    case LEFT: // 左边缘
                        left(v, dx);
                        break;
                    case RIGHT:
                        right(v, dx);
                        break;
                    default:
                        break;
                }
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                break;
            default:
                break;
        }
    }

    /**
     * 触摸点为左边缘
     *
     * @param v
     * @param dx
     */
    private void left(View v, int dx) {
//        Log.e(TAG, "...left ..." + dx);
//        dleft += dx;
//        if (dleft < -offset) {
//            dleft = -offset;
//        }
//        if (dright - dleft - 2 * offset < 200) {
//            dleft = dright - 2 * offset - 200;
//        }

//        width -= dx;
//        if (width < 120) {
//            width = 120;
//        }
//
//        if(llContent!=null){
//            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) llContent.getLayoutParams();
//            layoutParams.width = width;
//            llContent.setLayoutParams(layoutParams);
//        }
    }

    private int width;
    private void right(View v, int dx) {
//        Log.e(TAG, "...right ..." + dx+"  "+width+"  "+llContent);
        width += dx;
        if (width < 120) {
            width = 120;
        }
        if(llContent!=null){
            ViewGroup.LayoutParams layoutParams = llContent.getLayoutParams();
            layoutParams.width = width;
            llContent.setLayoutParams(layoutParams);
        }
    }

    /**
     * 通过坐标和移动距离，确定移动方向
     *
     * @param v
     * @param x
     * @param y
     * @return
     */
    private int getDirection(View v, int x, int y) {
//        Log.e(TAG, "getDirection: " + x + "   " + y);
        int left = v.getLeft();
        int right = v.getRight();
        int bottom = v.getBottom();
        int top = v.getTop();

        if (x < offset) {
//            Log.e(TAG, "getDirection: left");
            return LEFT;
        }
//        if (y < offset) {
//            return TOP;
//        }
        if ((right - left) - x < offset) {
//            Log.e(TAG, "getDirection: right");
            return RIGHT;
        }
//        if ((bottom - top) - y < offset) {
//            return BOTTOM;
//        }
//        Log.e(TAG, "getDirection: 中间");
        return CENTER;
    }
}
